#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>

using namespace std;

#define MAXSIZE 1024
#define PROMPT "[%s@%s %s]# "
#define SEP " "

//创造一个全局缓冲区，用于存储Getpwd中的路径
char cwd[MAXSIZE];

//解析命令全局变量
int g_argc = 0;
char* g_argv[MAXSIZE];
static int lastcode = 0;

const char* GetUser()
{
	const char* user = getenv("USER");
	return (user == NULL) ? "" : user;
}

const string GetHostName()
{
    string hostname_str;

    // 获取用户名
    string user = GetUser();
    // 追加后缀
    hostname_str += user + "-virtual-machine";

    return hostname_str; 
}

const string GetPwd()
{
	const char* pwd = getcwd(cwd, sizeof(cwd));
	
	if(pwd == NULL){
		perror("getcwd() error");
		return "None";
	}
	
	string str = pwd;
	int pos = str.rfind("/");
	str = str.substr(pos+1);
	
	return str;
}

void MakeCommandLine(char* CommandLine, int size){
	snprintf(CommandLine, size, PROMPT, GetUser(), GetHostName().c_str(), GetPwd().c_str());
}

void PrintCommand(char* CommandLine){
	printf("%s ", CommandLine);
	fflush(stdout);
}

bool GetCommand(char* out, int size){
	char* c = fgets(out, size, stdin);
	if(c == NULL)
		return false;
		
	out[strlen(out)-1] = 0;
	if(strlen(out) == 0)
		return false;
	
	return true;
}

bool CommandParse(char* commandline)
{
	g_argc = 0;
	g_argv[g_argc] = strtok(commandline, SEP);
	if(g_argv[g_argc] == NULL) return false;
	g_argc++;
	
	while((g_argv[g_argc] = strtok(nullptr, SEP)) != NULL){
		g_argc++;
	}
	if(g_argc > 0)
		return true;
		
	return false;
}

int  Execute()
{
	pid_t id = fork();
	if(id == 0){
		//子进程
		execvp(g_argv[0], g_argv);
		exit(1);
	}
	
	int status = 0;
	pid_t rid = waitpid(id, &status, 0);
	if(rid > 0){
		lastcode = WEXITSTATUS(status);
	}
	
	return 0;
}

string GetHome(){
	return getenv("HOME");
}

bool Cd(){
	if(g_argc == 1){
		//只有cd，跳转到家目录
		string homepath = GetHome();
		if(homepath.empty())
			return true;
		chdir(homepath.c_str());
	}
	else{
		string where = g_argv[1];
		if(where == "~"){
			string homepath = GetHome();
			chdir(homepath.c_str());
		}
	}
	return true;
}

void Echo(){
	if(g_argc <= 1){
		cout<<endl;
		lastcode = 0;
		return;
	}
	
	for(int i=1;i<g_argc;i++){
		string current = g_argv[i];
		if(current == "$?"){
			cout<<lastcode<<endl;
		}
		else if(current.length() > 1 && current[0] == '$'){
			string env_name = current.substr(1);
			const char* env_value = getenv(env_name.c_str());
			
			if(env_value)
				cout<<env_value;
		}
		
		if(i < g_argc-1)
			cout<<" ";
			
		else
			cout<<endl;
	}
	lastcode = 0;
}

bool CheckAndExecBuiltin()
{
	string cmd = g_argv[0];
	if(cmd == "cd"){
		Cd();
		return true;
	}
	else if(cmd == "echo"){
		Echo();
		return true;
	}
}

int main()
{
	while(1){
		char CommandLine[MAXSIZE];
		//1、提示符生成
		MakeCommandLine(CommandLine, sizeof(CommandLine));
		PrintCommand(CommandLine);
		
		//2、输入命令
		char out[MAXSIZE];
		if(!GetCommand(out, sizeof(out)))
			continue;
		
		//3、解析命令
		if(!CommandParse(out))
			continue;
		
		//4、检查是否为内建命令
		if(CheckAndExecBuiltin())
			continue;
		
		//5、执行外部命令
		Execute();	
	}

	return 0;
}
